#pragma once

#include <QThread>
#include <QSettings>
#include <QStringList>
#include <memory>
#include "SerialPort.h"
#include "Database.h"

class Worker : public QThread
{
    Q_OBJECT

public:
    Worker(QSettings* ini); 

public slots:
	bool Stop(unsigned timeout = 0);

public slots:
    void ProcessBarCode(const QByteArray& code);

signals:
    void Message(const QString&, int, const QString&);
    void connectDb();

public:
    QByteArray GetScanPreamble();
    QByteArray GetScanPostamble();

private slots:
    void InitializeDatabase();    

private:
	virtual void run();

private:
    bool InitializeSerial();
    bool InitializeDatabaseImpl(QSqlDatabasePtr db, const QString& iniSection);
    void DisconnectDatabase();
    void DisconnectDatabaseImpl(QSqlDatabasePtr db);
    void DisconnectSerial();

private:
    QByteArray GetDataFromDatabase(QSqlDatabasePtr db, 
                                   const QString& query, 
                                   const QString& fieldSeparator = ";", 
                                   const QString& recordSeparator = "\n");
    
    QString SaveData(const QByteArray& data);
    quint64 ConvertCode(const QByteArray& code);

private:
    Serial* GetSerial() const;

private:
    void AppendError(const QString& error);

private:
    ISimpleChannelPtr _serial;
    QSqlDatabasePtr   _sqlSource;
    QSqlDatabasePtr   _sqlDestination;

private:
    QSettings*  _ini;
    QString     _savePath;
    QString     _extension;
    QByteArray  _code;
    bool        _ignoreRS232;
    bool        _ignoreDatabase;
    quint64     _codeConst;
    QString     _fieldSeparator;
    QString     _recordSeparator;
    QByteArray  _scanPreamble;
    QByteArray  _scanPostamble;

private:
    QStringList _errors;
};

typedef std::tr1::shared_ptr<Worker> WorkerPtr;
